package com.googlecode.avianey.jersey;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;

@Path("/")
@Produces("application/json")
@Consumes("application/json")
public class JerseyJPAService {

    private static final EntityManagerFactory EMF =
            Persistence.createEntityManagerFactory("pu");

    /**
     * Add a new element
     * @param value
     */
    @PUT
    @Path("/{key: \\w+}")
    public void put(@PathParam("key") String key, String value) {
        if (value == null) {
            // HTTP 400 : Bad Request
            throw new WebApplicationException(400);
        }
        JerseyJPABean bean = new JerseyJPABean();
        bean.setKey(key);
        bean.setValue(value);
        EntityManager em = EMF.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(bean);
            em.getTransaction().commit();
        } catch (PersistenceException e) {
            if (get(key) != null) {
                // HTTP 409 : Conflict
                throw new WebApplicationException(409);
            } else {
                // HTTP 500 : Internal Server Error
                throw new WebApplicationException(500);
            }
        } finally {
            if (em.getTransaction().isActive()) {
                try {
                    em.getTransaction().rollback();
                } catch (Exception e) {}
            }
            em.close();
        }
    }

    /**
     * Update an existing element
     * @param bean
     */
    @POST
    @Path("/{key: \\w+}")
    public void update(@PathParam("key") String key, String value) {
        if (value == null || value.trim().length() == 0) {
            // Delete existing stored value
            delete(key);
        } else {
            EntityManager em = EMF.createEntityManager();
            try {
                em.getTransaction().begin();
                JerseyJPABean bean = (JerseyJPABean) em.getReference(JerseyJPABean.class, key);
                bean.setValue(value);
                em.merge(bean);
                em.getTransaction().commit();
            } catch (EntityNotFoundException e) {
                // HTTP 404 : Not Found
                throw new WebApplicationException(404);
            } catch (PersistenceException e) {
                // HTTP 500 : Internal Server Error
                throw new WebApplicationException(500);
            } finally {
                if (em.getTransaction().isActive()) {
                    try {
                        em.getTransaction().rollback();
                    } catch (Exception e) {}
                }
                em.close();
            }
        }
    }
    
    /**
     * Retrieve a persisted element
     * @param key
     * @return
     */
    @GET
    @Path("/{key: \\w+}")
    public String get(@PathParam("key") String key) {
        EntityManager em = EMF.createEntityManager();
        try {
            JerseyJPABean bean = (JerseyJPABean) em.getReference(JerseyJPABean.class, key);
            return bean.getValue();
        } catch (EntityNotFoundException e) {
            // HTTP 404 : Not Found
            throw new WebApplicationException(404);
        } finally {
            em.close();
        }
    }
    
    /**
     * Delete a persisted element
     * @param key
     */
    @DELETE
    @Path("/{key: \\w+}")
    public void delete(@PathParam("key") String key) {
        EntityManager em = EMF.createEntityManager();
        try {
            em.getTransaction().begin();
            Query q = em.createQuery("DELETE JerseyJPABean WHERE key = :key");
            q.setParameter("key", key);
            if (q.executeUpdate() == 0) {
                // HTTP 404 : Not Found
                throw new WebApplicationException(404);
            }
            em.getTransaction().commit();
        } catch (Exception e) {
            // HTTP 500 : Internal Server Error
            throw new WebApplicationException(500);
        } finally {
            if (em.getTransaction().isActive()) {
                try {
                    em.getTransaction().rollback();
                } catch (Exception e) {}
            }
            em.close();
        }
    }

}
